package com.weilele.mvvm.view

import android.content.Context
import android.graphics.Rect
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.View
import androidx.core.view.ViewCompat
import androidx.core.view.children
import androidx.customview.widget.ViewDragHelper
import com.weilele.mvvm.utils.activity.hadScrollToBottom
import com.weilele.mvvm.utils.activity.hadScrollToEnd
import com.weilele.mvvm.utils.activity.hadScrollToStart
import com.weilele.mvvm.utils.activity.hadScrollToTop
import com.weilele.mvvm.widget.BaseLinearLayout

/**
 * 拖拽子view
 * 类似于[ChildUnConsumedView]
 * 但是这个不支持嵌套滚动
 */
open class DragChildLayout : BaseLinearLayout {
    constructor(context: Context) : super(context)
    constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
    constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr)

    private val call = object : ViewDragHelper.Callback() {
        override fun tryCaptureView(child: View, pointerId: Int): Boolean {
            return true
        }

        override fun onViewDragStateChanged(state: Int) {
            super.onViewDragStateChanged(state)
        }

        override fun onViewPositionChanged(changedView: View, left: Int, top: Int, dx: Int, dy: Int) {
            super.onViewPositionChanged(changedView, left, top, dx, dy)
        }

        override fun onViewCaptured(capturedChild: View, activePointerId: Int) {
            super.onViewCaptured(capturedChild, activePointerId)
        }

        override fun onViewReleased(releasedChild: View, xvel: Float, yvel: Float) {
            super.onViewReleased(releasedChild, xvel, yvel)
            drag.smoothSlideViewTo(releasedChild, 0, 0)
            ViewCompat.postInvalidateOnAnimation(this@DragChildLayout)
        }

        override fun onEdgeTouched(edgeFlags: Int, pointerId: Int) {
            super.onEdgeTouched(edgeFlags, pointerId)
        }

        override fun onEdgeLock(edgeFlags: Int): Boolean {
            return super.onEdgeLock(edgeFlags)
        }

        override fun onEdgeDragStarted(edgeFlags: Int, pointerId: Int) {
            super.onEdgeDragStarted(edgeFlags, pointerId)
        }

        override fun getOrderedChildIndex(index: Int): Int {
            return super.getOrderedChildIndex(index)
        }

        override fun getViewHorizontalDragRange(child: View): Int {
            return super.getViewHorizontalDragRange(child)
        }

        override fun getViewVerticalDragRange(child: View): Int {
            return super.getViewVerticalDragRange(child)
        }

        override fun clampViewPositionHorizontal(child: View, left: Int, dx: Int): Int {
            return left
        }

        override fun clampViewPositionVertical(child: View, top: Int, dy: Int): Int {
            return top
        }
    }


    private val drag: ViewDragHelper by lazy { ViewDragHelper.create(this, call) }

    private fun getTouchView(x: Int, y: Int): View? {
        val rect = Rect()
        children.forEach {
            rect.set(it.left, it.top, it.right, it.bottom)
            if (rect.contains(x, y)) {
                return it
            }
        }
        return null
    }

    private var touchX = 0f
    private var touchY = 0f
    private var isHadTouchSlop = false

    override fun onInterceptTouchEvent(ev: MotionEvent): Boolean {
        val intercept = drag.shouldInterceptTouchEvent(ev)
        when (ev.action) {
            MotionEvent.ACTION_DOWN -> {
                isHadTouchSlop = false
                touchX = ev.rawX
                touchY = ev.rawY
            }
            MotionEvent.ACTION_MOVE -> {
                if (isHadTouchSlop) {
                    return true
                }
                val offX = touchX - ev.rawX
                val offY = touchY - ev.rawY
                val onlyChild = getTouchView(ev.x.toInt(), ev.y.toInt())
                val scaledPagingTouchSlop = drag.touchSlop
                if ((offX > scaledPagingTouchSlop && onlyChild?.hadScrollToEnd() == true)
                        || (offX < -scaledPagingTouchSlop && onlyChild?.hadScrollToStart() == true)
                        || (offY > scaledPagingTouchSlop && onlyChild?.hadScrollToBottom() == true)
                        || (offY < -scaledPagingTouchSlop && onlyChild?.hadScrollToTop() == true)
                ) {
                    //发生了滑动
                    isHadTouchSlop = true
                    ev.action = MotionEvent.ACTION_DOWN
                    drag.processTouchEvent(ev)
                    return true
                }
            }
            MotionEvent.ACTION_CANCEL, MotionEvent.ACTION_UP -> {
                if (isHadTouchSlop) {
                    isHadTouchSlop = false
                }
            }
        }
        return intercept
    }

    override fun onTouchEvent(event: MotionEvent): Boolean {
        drag.processTouchEvent(event)
        return true
    }

    override fun computeScroll() {
        if (drag.continueSettling(true)) {
            ViewCompat.postInvalidateOnAnimation(this)
        }
    }
}